/******************************************************************************
 *
 * @file       tcpmgr.h
 * @brief      因为聊天服务要维持一个长链接，方便服务器和客户端双向通信，那么就需要一个TCPMgr来管理TCP连接。
 *
 * @author     ario
 * @date       2024/06/08
 * @history
 *****************************************************************************/

#ifndef TCPMGR_H
#define TCPMGR_H

#include <QObject>
#include <QTcpSocket>
#include "global.h"
#include "singleton.h"
#include "userdata.h"

class SearchInfo;
class TcpMgr
        : public QObject
        , public Singleton<TcpMgr>                          // 单例基类
        , public std::enable_shared_from_this<TcpMgr>       // 可被分享类
{
    Q_OBJECT
    friend class Singleton;
public:
    ~TcpMgr();

private:
    TcpMgr();
    void initHandlers();
    void handleMsg(ReqId reqid, int len, QByteArray data);

public slots:
    void slot_tcp_connect(ServerInfo);                      // 登录界面创建tcp连接的信号的槽函数，连接聊天服务器
    void slot_send_data(ReqId reqId, QByteArray dataBytes);         // sig_send_data发送数据信号的槽函数

signals:
    void sig_con_success(bool bsuccess);                    // tcp连接结束发送的信号，包含连接结果
    void sig_send_data(ReqId reqId, QByteArray data);       // 要发送数据发送的信号（保证线程安全，发送数据前先发送信号）
    void sig_login_failed(int err);                         // 给登录界面发送登录失败信号
    void sig_switch_chatdlg();                              // 给登陆界面发送切换到聊天界面信号
    void sig_user_search(std::shared_ptr<SearchInfo>);      // 用户搜索发送的信号
    void sig_friend_apply(std::shared_ptr<AddFriendApply>);
    void sig_add_auth_friend(std::shared_ptr<AuthInfo>);
    void sig_auth_rsp(std::shared_ptr<AuthRsp>);
    void sig_text_chat_msg(std::shared_ptr<TextChatMsg>);

private:
    QString     _host;              // 服务器绑定的ip地址
    uint16_t    _port;              // 服务器绑定的端口号
    QTcpSocket  _socket;            // 服务器通信的socket
    QByteArray  _buffer;            // 读写缓存
    bool        _b_recv_pending;    // 是否读完客户端发来的消息
    quint16     _message_id;        // 报文编号
    quint16     _message_len;       // 报文长度
    QMap<ReqId, std::function<void(ReqId, int, QByteArray)>> _handlers;   // 不同消息的回调函数
};

#endif // TCPMGR_H
